package logic;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.Vector;

import javax.swing.DefaultListModel;

 
public class Server {
	public static char CR = '\r';
	public static char LF = '\n';
	public static int deleteRepeats = 3;
	public static int restoreRepeats = 5;
	public static int backupRepeats = 5;
	public static int delay = 400;
	public static int delayBackup = 500;
	public static int maxSize = 64000;
	private final int MC_port;
	public final String FILES="files"; 
	public final static String CHUNKS="chunks";
	private final int MDB_port;
	private final int MDR_port;
	private final InetAddress MC_address;
	private final InetAddress MDB_address;
	private final InetAddress MDR_address;
	private final MulticastSocket	MC_socket;
	private final MulticastSocket	MDB_socket;
	private final MulticastSocket	MDR_socket;
	private static FileRepository fileRepository;
	private static ChunkRepository chunkRepository;
	private List<StoredMessage> storedMessages;
	private List<PutchunkMessage> putchunkMessages;
	private List<PutchunkMessage> putchunkBlackList;
	private List<ChunkMessage> chunkMessages;
	private List<DeletedMessage> deletedMessages;
	public static final String defautVersion="1.0";
	public static String VERSION="2.0";
	public static int port=1234;
	public static boolean enhancement=false;
	private DatagramSocket socketChunks;
	private DeletedFiles deletedFiles;
	private static int spaceControlInterval = 60000;//300000 = 5min
	private static int spaceControlPerc = 80;//executa o controlo acima deste valor de ocupacao em percentagem

	public static DefaultListModel<String> logMensagesStr;

	public static void main(String[] args)throws Exception {

		Server server = new Server(args);

		try
		{
			FileInputStream fileIn =new FileInputStream(CHUNKS);

			ObjectInputStream in = new ObjectInputStream(fileIn);
			setChunkRepository((ChunkRepository) in.readObject());
			in.close();

		}catch(IOException i)
		{
			System.out.print("Size of Repository (in MB): ");
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			long nSize=Integer.parseInt(br.readLine());
			nSize=nSize*1024*1024;
			Server.setChunkRepository(new ChunkRepository(nSize));
		}
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Wants to use improvements? (y/n)");
		String str=br.readLine();
		if(str.equals("y")|| str.equals("Y"))
			Server.enhancement=true;
		else
			Server.enhancement=false;


		if(enhancement==true)
		{
			System.out.println("Number of Version: ");
			str=br.readLine();
			Server.VERSION=str;
			boolean valido=true;
			do{
				System.out.println("Number of Port: ");
				str=br.readLine();
				try
				{
					Server.port=Integer.parseInt(str);
				}
				catch(Exception e)
				{
					valido=false;
				}
			}while(!valido);
		}


		server.run();




		while(true)
		{
			System.out.println("Distributed Backup Service\n");
			System.out.println("1 - Backup File");
			System.out.println("2 - Restore File");
			System.out.println("3 - Delete File");
			System.out.println("4 - Remove Chunk");
			System.out.println("5 - Reclaim Space");
			System.out.println("6 - ShowLog");
			System.out.println("7 - Exit");
			System.out.println(getFileRepository().getFiles().size()+" Files");
			System.out.println(getChunkRepository().getChunks().size()+" Chunks");

			String input=br.readLine();
			try{

				switch(Integer.parseInt(input))
				{
				case 1:
				{
					server.backup();
					break;
				}
				case 2:
				{
					server.restore();
					break;
				}
				case 3:
				{
					server.delete();
					break;
				}
				case 4:
				{
					server.remove();
					break;
				}
				case 5:
				{
					server.reclaim();
					break;
				}
				case 6:
				{
					server.showLog();
					break;
				}
				case 7:
				{
					server.exit();
					System.exit(0);
				}
				default:
				{
					break;
				}
				}
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}




	}
	private void showLog() {
		System.out.println("Log");
		for(int i=0;i<Server.logMensagesStr.size();i++)
		{
			System.out.println(Server.logMensagesStr.get(i));
		}

	}
	private void backup() throws Exception {

		System.out.println("Name of file:");

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String strName=br.readLine();

		System.out.println("Replication Degree:");
		String strRep = br.readLine();
		int replicationDeg = Integer.parseInt(strRep);

		backupFile(strName, replicationDeg);


	}
	private void restore() throws Exception {


		if(getFileRepository().getFiles().size()==0)
		{
			System.out.println("You haven't files in backup.");
			return;
		}

		System.out.println("Select number of file:");

		for(int i = 0; i< getFileRepository().getFiles().size();i++)
		{	
			System.out.print(i+1);
			System.out.println(" - "+getFileRepository().getFiles().elementAt(i).getName());
		}

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int nfile=Integer.parseInt(br.readLine());
		myFile file = getFileRepository().getFiles().elementAt(nfile-1);

		restoreFile(file);


	}
	private void delete() throws IOException {

		System.out.println("Name of file:");

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String nameFile=br.readLine();

		for(int i = 0; i< getFileRepository().getFiles().size();i++)
		{	
			myFile file = getFileRepository().getFiles().elementAt(i);

			if(file.getName().equals(nameFile))
			{


				try {
					deleteFile(file);
				} catch (InterruptedException e) {
					//e.printStackTrace();
				}

				return;


			}
		}


	}
	private void remove() throws IOException {
		boolean exit = false;
		while(!exit){
			if(getChunkRepository().getChunks().size()==0)
			{
				System.out.println("You haven't chunks in backup.");
				return;
			}
			for(int i =0; i<getChunkRepository().getChunks().size();i++)
			{
				Chunk chunk = getChunkRepository().getChunks().elementAt(i);
				System.out.println(i+1+" - " + chunk.getFileID()+" " + chunk.getChunkNo());
			}
			System.out.println("0 - Exit ");
			System.out.println("Chunk to remove: ");
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			String input = br.readLine();

			try{
				int option = Integer.parseInt(input);
				if(option ==0)
				{
					exit=true;
				}
				else if(option <= getChunkRepository().getChunks().size())
				{
					Chunk chunk = getChunkRepository().getChunks().elementAt(option-1);

					exit=removeChunk(chunk);

				}


			}catch(NumberFormatException | IOException e){
				e.printStackTrace();
			}

		}

	}
	private void reclaim() throws IOException {
		System.out.println("Space to reclaim(bytes): ");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String input = br.readLine();
		long sizeReclaim = Long.parseLong(input);

		reclaimSpace(sizeReclaim,false);
	}
	public void exit() throws Exception {


		Server.getFileRepository().saveInFile(FILES);
		Server.getChunkRepository().saveInFile(CHUNKS);

		MC_socket.leaveGroup(getMC_address());
		MDB_socket.leaveGroup(MDB_address);
		MDR_socket.leaveGroup(getMDR_address());

		MC_socket.close();
		MDB_socket.close();
		MDR_socket.close();

	}
	public Server(String[] args)throws Exception
	{
		MC_address = InetAddress.getByName(args[0]);
		MC_port = Integer.parseInt(args[1]);
		MDB_address = InetAddress.getByName(args[2]);
		MDB_port = Integer.parseInt(args[3]);
		MDR_address = InetAddress.getByName(args[4]);
		MDR_port = Integer.parseInt(args[5]);
		MC_socket = new MulticastSocket(getMC_port());
		MDB_socket = new MulticastSocket(getMDB_port());
		MDR_socket = new MulticastSocket(getMDR_port());
		//Server.logMensages=new ArrayList<LogMensage>();
		Server.logMensagesStr=new DefaultListModel<String>();
		setDeletedFiles(new DeletedFiles());	
		setStoredMessages(Collections.synchronizedList(new LinkedList<StoredMessage>()));
		setPutchunkMessages(Collections.synchronizedList(new LinkedList<PutchunkMessage>()));
		setPutchunkBlackList(Collections.synchronizedList(new LinkedList<PutchunkMessage>()));
		setChunkMessage(Collections.synchronizedList(new LinkedList<ChunkMessage>()));
		setDeletedMessages(Collections.synchronizedList(new LinkedList<DeletedMessage>()));



	}
	public void run()throws Exception
	{

		if(enhancement){
			socketChunks=new DatagramSocket(port);
			socketChunks.setSoTimeout(1000);
		}

		MC_socket.setTimeToLive(1);
		MDB_socket.setTimeToLive(1);
		MDR_socket.setTimeToLive(1);



		MC_socket.setLoopbackMode(true);
		MDB_socket.setLoopbackMode(true);
		MDR_socket.setLoopbackMode(true);


		MC_socket.joinGroup(getMC_address());
		MDB_socket.joinGroup(getMDB_address());
		MDR_socket.joinGroup(getMDR_address());

		//Load file FILES
		try
		{
			FileInputStream fileIn =new FileInputStream(FILES);
			@SuppressWarnings("resource")
			ObjectInputStream in = new ObjectInputStream(fileIn);
			setFileRepository((FileRepository) in.readObject());

		}catch(IOException i)
		{
			Server.setFileRepository(new FileRepository());
		}

		//	load a file CHUNKS


		ThreadMessages t_storeds=new ThreadMessages(this); //thread que le a lista de storeds
		t_storeds.start();

		ThreadMC mc_channel=new ThreadMC(this);//thread que le o canal de controlo
		mc_channel.start();

		ThreadMDB mdb_channel=new ThreadMDB(this);//thread que le o canal de backup
		mdb_channel.start();

		ThreadMDR mdr_channel=new ThreadMDR(this);//thread que le o canal de restore
		mdr_channel.start();

		Timer timer = new Timer();
		timer.schedule( new SpaceControl(this), 2000, getSpaceControlInterval());   

		if(enhancement)
			sendHello();

	}
	public void sendHello()
	{
		try {
			byte[] sendData = new byte[65000];
			String reply = new String("HELLO "+Server.VERSION+CR+LF+CR+LF);
			sendData=reply.getBytes();
			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getMC_address(), getMC_port());

			getMC_socket().send(sendPacket);
			LogMensage lm=new LogMensage("SEND HELLO");

			Server.logMensagesStr.insertElementAt(lm.str(), 0);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void backupFile(String strName, int replicationDeg) throws IOException, InterruptedException {

		myFile newFile=new myFile();
		boolean find=false;
		boolean backupRepFailed=false;
		for(int i=0;i<Server.getFileRepository().getFiles().size();i++)
		{
			if(Server.getFileRepository().getFiles().get(i).getName().equals(strName))
			{
				find=true;
				newFile=Server.getFileRepository().getFiles().get(i);
				break;
			}
		}
		if(!find)
		{
			newFile.setName(strName);
			newFile.encoding();

		}
		newFile.setReplicationDeg(replicationDeg);

		InputStream is = new FileInputStream(newFile.getName());

		int size = is.available();

		int chunkCount = 0;
		LogMensage lm=new LogMensage("INFO - "+newFile.getName()+"'s backup started.");
		Server.logMensagesStr.insertElementAt(lm.str(),0);
		byte[] content = new byte[maxSize];
		int n=is.read(content,0,maxSize);
		while(n!=-1){//preenchimento das mensagens e envio dos chunks de um ficheiro




			String chunk = new String("PUTCHUNK "+defautVersion+" "+newFile.getId()+" "+chunkCount+" "+replicationDeg+CR+LF+CR+LF);//+content);
			byte[] sendData;

			sendData=chunk.getBytes();

			byte[] sendData2 = new byte[sendData.length+n];

			for(int i=0;i<sendData.length;i++)
			{

				sendData2[i]=new Byte(sendData[i]);

			}
			for(int i=0;i<n;i++)
			{

				sendData2[sendData.length+i]=new Byte(content[i]);

			}




			DatagramPacket sendPacket = new DatagramPacket(sendData2, sendData.length+n, MDB_address, MDB_port);

			long delayTemp =delayBackup;
			Vector<String> ips=new Vector<String>();

			for(int i =0 ; i < backupRepeats; i++)
			{
				ips.clear();
				getMDB_socket().send(sendPacket);
				lm=new LogMensage("SEND PUTCHUNK (B) - "+" File Name: "+newFile.getName() + "Chunck number: "+chunkCount);
				Server.logMensagesStr.insertElementAt(lm.str(),0);
				Thread.sleep(delayTemp);

				for(int j=0;j<storedMessages.size();j++)
				{
					if(storedMessages.get(j).getChunkNo()== chunkCount 
							&& storedMessages.get(j).getFileID().equals(newFile.getId()))
					{
						if(!ips.contains(storedMessages.get(j).getIp()))
						{
							ips.add(storedMessages.get(j).getIp());
							storedMessages.remove(j);
							j--;

						}
					}

				}
				
				if(ips.size()>=replicationDeg)
					break;

				delayTemp +=delayBackup;
			}
			if(ips.size()<replicationDeg)
				backupRepFailed= true;
			newFile.ipsAdd(ips);

			chunkCount++;
			n=is.read(content,0,maxSize);

		}
		if((float)(size%maxSize)==0)//no caso de ser multiplo do tamanho maximo enviar um pacote com o body vazio
		{	 
			String chunk = new String("PUTCHUNK "+defautVersion+" "+newFile.getId()+" "+chunkCount+" "+replicationDeg+CR+LF+CR+LF);
			byte[] sendData = new byte[65000];

			sendData=chunk.getBytes();

			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, MDB_address, MDB_port);
			long delayTemp =delayBackup;
			Vector<String> ips=new Vector<String>();

			for(int i =0 ; i < backupRepeats; i++)
			{
				ips.clear();
				MDB_socket.send(sendPacket);
				lm=new LogMensage("SEND PUTCHUNK (B) - "+" File Name: "+newFile.getName() + "Chunck number: "+chunkCount);
				Server.logMensagesStr.insertElementAt(lm.str(),0);
				Thread.sleep(delayTemp);
				for(int j=0;j<storedMessages.size();j++)
				{
					if(storedMessages.get(j).getChunkNo()== chunkCount 
							&& storedMessages.get(j).getFileID().equals(newFile.getId()))
					{
						if(!ips.contains(storedMessages.get(j).getIp()))
						{
							ips.add(storedMessages.get(j).getIp());
							storedMessages.remove(j);
							j--;

						}
					}

				}
				if(ips.size()>=replicationDeg)
					break;

				delayTemp +=delayTemp;
			}
			if(ips.size()<replicationDeg)
				backupRepFailed = true;
			newFile.ipsAdd(ips);


		}
		if(backupRepFailed)
			lm=new LogMensage("INFO - "+newFile.getName()+"'s backup ended without replication degree desired.");
		else
			lm=new LogMensage("INFO - "+newFile.getName()+"'s backup ended.");
		Server.logMensagesStr.insertElementAt(lm.str(),0);
		newFile.setNumChunks(chunkCount);
		is.close();
		if(!find)
			Server.getFileRepository().addFile(newFile);
		Server.getFileRepository().saveInFile(FILES);

	}
	public void restoreFile(myFile file) throws IOException, InterruptedException {

		FileOutputStream out = new FileOutputStream(new File(file.getName()));
		out.flush();

		for(int chunkNo=0;chunkNo < file.getNumChunks();chunkNo++)
		{
			String chunk;
			if(enhancement)
			{
				chunk = new String("GETCHUNK "+VERSION+" "+file.getId()+" "+chunkNo+" "+Server.port+CR+LF+CR+LF);
			}
			else
			{
				chunk = new String("GETCHUNK "+defautVersion+" "+file.getId()+" "+chunkNo+CR+LF+CR+LF);
			}

			byte[] sendData = new byte[65000];

			sendData=chunk.getBytes();

			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getMC_address(), getMC_port());

			MC_socket.send(sendPacket);
			LogMensage lm=new LogMensage("SEND GETCHUNK - "+" File Name: "+file.getName());
			Server.logMensagesStr.insertElementAt(lm.str(),0);
			boolean received = false;
			int countRepeats = restoreRepeats;
			long delayTemp=delay;
			if(!enhancement)
			{
				while(!received && countRepeats >0){

					countRepeats--;
					try{

						ChunkMessage ch = new ChunkMessage(file.getId(), chunkNo);
						//System.out.println(getChunkMessage().size());
						if(getChunkMessage().contains(ch))
						{
							int index  = getChunkMessage().indexOf(ch);
							out.write(getChunkMessage().get(index).getContent());
							received=true;

						}
						else{
							received=false;
							delayTemp+=delayTemp;
							Thread.sleep(delayTemp);
						}
					}catch (SocketTimeoutException | SocketException | InterruptedException  e) {
						delayTemp+=delayTemp;
						Thread.sleep(delayTemp);
						e.printStackTrace();
						received=false;

					}


				}
			}
			else
			{

				while(!received && countRepeats >0){


					byte[] receiveData=new byte[65000]; 
					countRepeats--;
					DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
					try{
						socketChunks.receive(receivePacket);
						String message_received = new String( receivePacket.getData(),0,receivePacket.getLength());
						String[] chunkParts=new String[10];
						int indexFinalHeader = message_received.indexOf("\r\n\r\n");
						String header = message_received.substring(0, indexFinalHeader);
						chunkParts=header.split(" ");
						String version=chunkParts[1];

						if(chunkParts[0].equals("CHUNK") && VERSION.equals(version) && chunkParts[2].equals(file.getId()) &&  chunkParts[3].equals(Integer.toString(chunkNo)))
						{

							int contentStart=message_received.indexOf("\r\n\r\n")+4;

							byte[] cont=new byte[receivePacket.getLength()-(contentStart)];
							for(int i=0;i<receivePacket.getLength()-contentStart;i++)
							{
								cont[i]=receiveData[contentStart+i];
							}
							out.write(cont);
							received=true;

						}
						else
						{
							System.out.println(countRepeats);
							Thread.sleep(delayTemp);
							received=false;
						}
					}catch(SocketTimeoutException | SocketException | InterruptedException  e)
					{
						System.out.println("aqui:"+countRepeats);
						Thread.sleep(delayTemp);
						received=false;
					}


				}

			}
			if(countRepeats ==0 && !received){
				out.close();
				(new File(file.getName())).delete();
				LogMensage lm1=new LogMensage("INFO - "+" Restore file: " + file.getName()+ " without success.");
				Server.logMensagesStr.insertElementAt(lm1.str(),0);
				System.out.println("Restore without success");
				return;
			}
			


		}
		LogMensage lm1=new LogMensage("INFO - "+" Restore file: " + file.getName()+ " with success.");
		Server.logMensagesStr.insertElementAt(lm1.str(),0);
		System.out.println("Restore with success");
		out.close();				
		return;

	}
	public void deleteFile(myFile file) throws IOException, InterruptedException
	{

		if(enhancement)//se as melhorias estiverem ligadas entao vai criar a lista de files apagados
		{
			for(int countChunk=0; countChunk < file.getIps().size(); countChunk++)
				getDeletedFiles().add(file.getId(), file.getIps().elementAt(countChunk));
		}

		String chunk = new String("DELETE "+file.getId()+CR+LF+CR+LF);
		
		byte[] sendData = new byte[65000];

		sendData=chunk.getBytes();

		DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getMC_address(), getMC_port());

		for(int repeats =0;repeats<deleteRepeats;repeats++)
		{
			getMC_socket().send(sendPacket);
			LogMensage lm;
			if(file.getName()== null)
				lm=new LogMensage("SEND DELETE - "+" File Name: "+file.getName());
			else
				lm=new LogMensage("SEND DELETE - "+" File ID: "+file.getId());
			Server.logMensagesStr.insertElementAt(lm.str(),0);
			Thread.sleep(delay);
		}
		getFileRepository().getFiles().remove(getFileRepository().getFile(file.getName()));
		getFileRepository().saveInFile(FILES);

	}
	public boolean removeChunk(Chunk chunk) throws IOException {
		File f = new File(chunk.getFileID()+chunk.getChunkNo());
		InputStream is = new FileInputStream(chunk.getFileID()+chunk.getChunkNo());
		int size = is.available();
		is.close();
		if(f.delete()){

			getChunkRepository().getChunks().remove(chunk);
			putchunkBlackList.add(new PutchunkMessage(chunk.getFileID(), chunk.getChunkNo()));
			String message = new String("REMOVED "+defautVersion+" "+chunk.getFileID()+" "+chunk.getChunkNo()+CR+LF+CR+LF);
			byte[] sendData = new byte[65000];
			sendData=message.getBytes();
			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getMC_address(), getMC_port());

			getMC_socket().send(sendPacket);	
			LogMensage lm=new LogMensage("SEND REMOVE - "+" FileID: "+chunk.getFileID() + " Chunk number: "+ chunk.getChunkNo());
			Server.logMensagesStr.insertElementAt(lm.str(),0);
			long newSpaceOccupied = getChunkRepository().getRepositorySpaceOccupied() - size; 
			getChunkRepository().setRepositorySpaceOccupied(newSpaceOccupied);
			getChunkRepository().saveInFile(CHUNKS);
			return true;

		}
		return false;

	}
	public synchronized boolean reclaimSpace(long space, boolean auto) // se o automatico for true,faz automatico,nao importa a variavel space, se for false
	{
		if(!auto)
		{
			if(getChunkRepository().getRepositorySpaceOccupied() >= space){

				long oldSpaceOccupied = getChunkRepository().getRepositorySpaceOccupied();
				LinkedList<Chunk> fila = getChunkRepository().getChunksToRemove(); // lista de chunks por ordem de prioridade para remover

				while(oldSpaceOccupied - getChunkRepository().getRepositorySpaceOccupied() < space ) 
				{
					try {
						if(fila.isEmpty())
							break;
						if(fila.peek()!= null){
							removeChunk(fila.peek());
							fila.remove();
						}
					} catch (IOException e) {
						//e.printStackTrace();
					}
				}

				return true;
			}
			else 
				return false;
		}
		else if(auto)
		{
			LinkedList<Chunk> fila = getChunkRepository().getChunksToRemove(auto);
			while(!fila.isEmpty() ) 
			{
				try {
					if(fila.peek()!= null){
						removeChunk(fila.peek());
						fila.remove();
					}
				} catch (IOException e) {
					//e.printStackTrace();
				}
			}
			return true;
		}
		return false;

	}
	public synchronized MulticastSocket getMC_socket()  {
		return MC_socket;
	}
	public synchronized MulticastSocket getMDB_socket() {
		return MDB_socket;
	}
	public synchronized MulticastSocket getMDR_socket() {
		return MDR_socket;
	}

	public int getMC_port() {
		return MC_port;
	}
	public InetAddress getMC_address() {
		return MC_address;
	}
	public InetAddress getMDR_address() {
		return MDR_address;
	}
	public int getMDR_port() {
		return MDR_port;
	}
	public InetAddress getMDB_address() {
		return MDB_address;
	}
	public int getMDB_port() {
		return MDB_port;
	}
	public synchronized static ChunkRepository getChunkRepository() {
		return chunkRepository;
	}
	public synchronized static void setChunkRepository(ChunkRepository chunkRepository) {
		Server.chunkRepository = chunkRepository;
	}
	public synchronized static FileRepository getFileRepository() {
		return fileRepository;
	}
	public synchronized static void setFileRepository(FileRepository fileRepository) {
		Server.fileRepository = fileRepository;
	}
	public synchronized List<PutchunkMessage> getPutchunkMessages() {
		return putchunkMessages;
	}
	public synchronized void setPutchunkMessages(List<PutchunkMessage> putchunkMessages) {
		this.putchunkMessages = putchunkMessages;
	}
	public synchronized List<StoredMessage> getStoredMessages() {
		return storedMessages;
	}
	public synchronized void setStoredMessages(List<StoredMessage> storedMessages) {
		this.storedMessages = storedMessages;
	}
	public synchronized List<PutchunkMessage> getPutchunkBlackList() {
		return putchunkBlackList;
	}
	public synchronized void setPutchunkBlackList(
			List<PutchunkMessage> putchunkBlackList) {
		this.putchunkBlackList = putchunkBlackList;
	}
	public String getDefautVersion() {
		return defautVersion;
	}
	public synchronized List<ChunkMessage> getChunkMessage() {
		return chunkMessages;
	}
	public synchronized void setChunkMessage(List<ChunkMessage> chunkMessage) {
		this.chunkMessages = chunkMessage;
	}
	public synchronized  DatagramSocket getSocketChunks() {
		return socketChunks;
	}
	public synchronized void setSocketChunks(DatagramSocket socketChunks) {
		this.socketChunks = socketChunks;
	}
	public synchronized DeletedFiles getDeletedFiles() {
		return deletedFiles;
	}
	public synchronized void setDeletedFiles(DeletedFiles deletedFiles) {
		this.deletedFiles = deletedFiles;
	}
	public synchronized List<DeletedMessage> getDeletedMessages() {
		return deletedMessages;
	}
	public synchronized void setDeletedMessages(List<DeletedMessage> deletedMessages) {
		this.deletedMessages = deletedMessages;
	}
	public static int getSpaceControlPerc() {
		return spaceControlPerc;
	}
	public static void setSpaceControlPerc(int spaceControlPerc) {
		Server.spaceControlPerc = spaceControlPerc;
	}
	public static int getSpaceControlInterval() {
		return spaceControlInterval;
	}
	public static void setSpaceControlInterval(int spaceControlInterval) {
		Server.spaceControlInterval = spaceControlInterval;
	}



}